const shortcuts = {
    ArrowUp: () => scrollTo(0, 0),
    ArrowDown: () => scrollTo(0, document.body.scrollHeight),
    '[': () => window.history.back(),
    ']': () => window.history.forward(),
    r: () => window.location.reload(),
    '-': () => zoomOut(),
    '=': () => zoomIn(),
    '+': () => zoomIn(),
    0: () => setZoom('100%'),
}

function setZoom(zoom) {
    const html = document.getElementsByTagName('html')[0]
    html.style.zoom = zoom
    window.localStorage.setItem('htmlZoom', zoom)
}

function zoomCommon(zoomChange) {
    const currentZoom = window.localStorage.getItem('htmlZoom') || '100%'
    setZoom(zoomChange(currentZoom))
}

function zoomIn() {
    zoomCommon((currentZoom) => `${Math.min(parseInt(currentZoom) + 10, 200)}%`)
}

function zoomOut() {
    zoomCommon((currentZoom) => `${Math.max(parseInt(currentZoom) - 10, 30)}%`)
}

function handleShortcut(event) {
    console.log('event.key')
    if (shortcuts[event.key]) {
        event.preventDefault()
        shortcuts[event.key]()
    }
}

// Judgment of file download.
function isDownloadLink(url) {
    console.log('is download link', url)
    const fileExtensions = [
        '3gp',
        '7z',
        'ai',
        'apk',
        'avi',
        'bmp',
        'csv',
        'dmg',
        'doc',
        'docx',
        'fla',
        'flv',
        'gif',
        'gz',
        'gzip',
        'ico',
        'iso',
        'indd',
        'jar',
        'jpeg',
        'jpg',
        'm3u8',
        'mov',
        'mp3',
        'mp4',
        'mpa',
        'mpg',
        'mpeg',
        'msi',
        'odt',
        'ogg',
        'ogv',
        'pdf',
        'png',
        'ppt',
        'pptx',
        'psd',
        'rar',
        'raw',
        'rss',
        'svg',
        'swf',
        'tar',
        'tif',
        'tiff',
        'ts',
        'txt',
        'wav',
        'webm',
        'webp',
        'wma',
        'wmv',
        'xls',
        'xlsx',
        'xml',
        'zip',
    ]
    const downloadLinkPattern = new RegExp(
        `\\.(${fileExtensions.join('|')})$`,
        'i'
    )
    return downloadLinkPattern.test(url)
}

// No need to go to the download link.
function externalDownLoadLink() {
    return ['quickref.me'].indexOf(location.hostname) > -1
}

// Directly jumping out without hostname address.
function externalTargetLink() {
    return ['zbook.lol'].indexOf(location.hostname) > -1
}

document.addEventListener('keyup', (event) => {
    console.log('add event listener keyup', event)
    if (/windows|linux/i.test(navigator.userAgent) && event.ctrlKey) {
        handleShortcut(event)
    }
    if (/macintosh|mac os x/i.test(navigator.userAgent) && event.metaKey) {
        handleShortcut(event)
    }
})

document.addEventListener('DOMContentLoaded', () => {
    console.log('eventjs DOMContentLoaded------')
    const tauri = window.__TAURI__
    const appWindow = tauri.window.appWindow
    const invoke = tauri.tauri.invoke

    const topDom = document.createElement('div')
    topDom.id = 'pack-top-dom'
    document.body.appendChild(topDom)
    const domEl = document.getElementById('pack-top-dom')

    domEl.addEventListener('touchstart', () => {
        appWindow.startDragging().then()
    })

    domEl.addEventListener('mousedown', (e) => {
        e.preventDefault()
        if (e.buttons === 1 && e.detail !== 2) {
            appWindow.startDragging().then()
        }
    })

    domEl.addEventListener('dblclick', () => {
        appWindow.isFullscreen().then((fullscreen) => {
            appWindow.setFullscreen(!fullscreen).then()
        })
    })

    // Collect blob urls to blob by overriding window.URL.createObjectURL
    function collectUrlToBlobs() {
        const backupCreateObjectURL = window.URL.createObjectURL
        window.blobToUrlCaches = new Map()
        window.URL.createObjectURL = (blob) => {
            const url = backupCreateObjectURL.call(window.URL, blob)
            window.blobToUrlCaches.set(url, blob)
            return url
        }
    }

    function convertBlobUrlToBinary(blobUrl) {
        return new Promise((resolve) => {
            const blob = window.blobToUrlCaches.get(blobUrl)
            const reader = new FileReader()

            reader.readAsArrayBuffer(blob)
            reader.onload = () => {
                resolve(Array.from(new Uint8Array(reader.result)))
            }
        })
    }

    function downloadFromDataUri(dataURI, filename) {
        const byteString = atob(dataURI.split(',')[1])
        // write the bytes of the string to an ArrayBuffer
        const bufferArray = new ArrayBuffer(byteString.length)

        // create a view into the buffer
        const binary = new Uint8Array(bufferArray)

        // set the bytes of the buffer to the correct values
        for (let i = 0; i < byteString.length; i++) {
            binary[i] = byteString.charCodeAt(i)
        }

        // write the ArrayBuffer to a binary, and you're done
        invoke('download_file_by_binary', {
            params: {
                filename,
                binary: Array.from(binary),
            },
        })
    }

    function downloadFromBlobUrl(blobUrl, filename) {
        convertBlobUrlToBinary(blobUrl).then((binary) => {
            invoke('download_file_by_binary', {
                params: {
                    filename,
                    binary,
                },
            })
        })
    }

    // detect blob download by createElement("a")
    function detectDownloadByCreateAnchor() {
        console.log('detectDownloadByCreateAnchor')
        const createEle = document.createElement

        document.createElement = (el) => {
            if (el !== 'a') return createEle.call(document, el)
            const anchorEle = createEle.call(document, el)
            // use addEventListener to avoid overriding the original click event.
            anchorEle.addEventListener(
                'click',
                (e) => {
                    console.log('anchorEle.addEventListener')
                    const url = anchorEle.href
                    const filename =
                        anchorEle.download || getFilenameFromUrl(url)
                    if (window.blobToUrlCaches.has(url)) {
                        downloadFromBlobUrl(url, filename)
                        // case: download from dataURL -> convert dataURL ->
                    } else if (url.startsWith('data:')) {
                        downloadFromDataUri(url, filename)
                    } else if (
                        isDownloadLink(url) ||
                        anchorEle.hostname !== window.location.host
                    ) {
                        handleExternalLink(e, url)
                    }
                },
                true
            )

            return anchorEle
        }
    }

    const isExternalLink = (link) => window.location.host !== link.host
    // process special download protocol['data:','blob:']
    const isSpecialDownload = (url) =>
        ['blob', 'data'].some((protocol) => url.startsWith(protocol))

    const isDownloadRequired = (url, anchorElement, e) =>
        anchorElement.download || e.metaKey || e.ctrlKey || isDownloadLink(url)

    const handleExternalLink = (e, url) => {
        console.log('handleExternalLink----')
        e.preventDefault()
        // tauri.shell.open(url)
    }

    const handleDownloadLink = (e, url, filename) => {
        console.log('handleDownloadLink----')
        e.preventDefault()
        invoke('download_file', { params: { url, filename } })
    }

    const detectAnchorElementClick = (e) => {
        console.log('detectAnchorElementClick----')
        const anchorElement = e.target.closest('a')
        console.log('anchorElement--', anchorElement.href)
        if (anchorElement && anchorElement.href) {
            anchorElement.target = '_self'
            const hrefUrl = new URL(anchorElement.href)
            const absoluteUrl = hrefUrl.href
            let filename =
                anchorElement.download || getFilenameFromUrl(absoluteUrl)
            // Handling external link redirection.
            if (
                isExternalLink(absoluteUrl) &&
                (['_blank', '_new'].includes(anchorElement.target) ||
                    externalTargetLink())
            ) {
                handleExternalLink(e, absoluteUrl)
                return
            }

            // Process download links for Rust to handle.
            if (
                isDownloadRequired(absoluteUrl, anchorElement, e) &&
                !externalDownLoadLink() &&
                !isSpecialDownload(absoluteUrl)
            ) {
                handleDownloadLink(e, absoluteUrl, filename)
            }
        }
    }

    // Prevent some special websites from executing in advance, before the click event is triggered.
    document.addEventListener('click', detectAnchorElementClick, true)

    collectUrlToBlobs()
    detectDownloadByCreateAnchor()

    // Rewrite the window.open function.
    const originalWindowOpen = window.open
    window.open = function (url, name, specs) {
        // Apple login and google login
        if (name === 'AppleAuthentication') {
            //do nothing
        } else if (specs.includes('height=') || specs.includes('width=')) {
            location.href = url
        } else {
            const baseUrl = window.location.origin + window.location.pathname
            const hrefUrl = new URL(url, baseUrl)
            // tauri.shell.open(hrefUrl.href)
        }
        // Call the original window.open function to maintain its normal functionality.
        return originalWindowOpen.call(window, url, name, specs)
    }

    // Set the default zoom, There are problems with Loop without using try-catch.
    try {
        setDefaultZoom()
    } catch (e) {
        console.log(e)
    }

    // Fix Chinese input method "Enter" on Safari
    document.addEventListener(
        'keydown',
        (e) => {
            if (e.keyCode === 229) e.stopPropagation()
        },
        true
    )
})

function setDefaultZoom() {
    const htmlZoom = window.localStorage.getItem('htmlZoom')
    if (htmlZoom) {
        setZoom(htmlZoom)
    }
}

function getFilenameFromUrl(url) {
    const urlPath = new URL(url).pathname
    return urlPath.substring(urlPath.lastIndexOf('/') + 1)
}
